home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue28 / hash / HASH.ZIP / hash.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-09-29  |  6.6 KB  |  293 lines

  1. //----------------------------------------------------------------------------
  2. // File:          hash.pas
  3. // Typ:           Delphi - Unit
  4. // Author:        Peter Welkenbach
  5. // Date:          28.09.97
  6. // Last update:   28.09.97
  7. // Compiler:      Delphi 3.0
  8. // Remarks:       Implementation of a hashtable using external chaining
  9. //
  10. //          uses the hash function used in ELF object files
  11. //
  12. //                c-source of hash-function (Attention: it's wrong there!!)
  13. //                was published in the Book:
  14. //
  15. //                A. Binstock, J. Rex (1995):
  16. //                Practical Algorithms for Programmers,
  17. //                Addison-Wesley
  18. //
  19. // Todo:          1.) check for existing objects with identical data
  20. //                2.) make hashtable persistent
  21. //----------------------------------------------------------------------------
  22. unit Hash;
  23.  
  24. interface
  25.  
  26. uses sysutils, classes;
  27.  
  28. type
  29.   THashObj = class(TObject)
  30.                private
  31.                  HashValue: integer;
  32.                public
  33.                  Name: string;
  34.                  Data: Pointer;
  35.               end;
  36.  
  37.  
  38.   THashSlot = class(TObject)
  39.               private
  40.                 SlotOfHashValue: integer;
  41.                 HashElements: TList;   // of THashObj
  42.  
  43.               protected
  44.                 constructor Create;
  45.                 destructor Destroy; override;
  46.  
  47.                 function GetObjByName( Name: pchar ): THashObj;
  48.               end;
  49.  
  50.  
  51.   THashTable = class(TList)
  52.                 private
  53.                   ClosestPrime: integer;
  54.                   HashElement: THashObj;
  55.  
  56.                   HashElementList: TList;
  57.  
  58.                   function ElfHash( name: pchar): integer;
  59.  
  60.                 public
  61.                   HashSlot: THashSlot;
  62.  
  63.                   constructor Create;
  64.                   destructor Destroy; override;
  65.                   procedure Init(Size: integer);  //
  66.                   procedure AddElementToSlot( Element: String; Data: Pointer);
  67.                   procedure DelElementFromSlot( Element: String );
  68.                   function CountElementsInSlot( SlotOfValues: String): integer;
  69.                   function GetElementFromSlot( Name: String): THashObj;
  70.                   function GetSlot( Slot: string): TList;
  71.               end;
  72.  
  73.  
  74.  
  75.  
  76. implementation
  77.  
  78. //--------------------------------------------------
  79. //
  80. //   THashSlot
  81. //
  82. //--------------------------------------------------
  83.  
  84. constructor THashSlot.Create;
  85. begin
  86.   inherited create;
  87.   HashElements:=Tlist.Create;
  88. end;
  89.  
  90.  
  91. destructor THashSlot.Destroy;
  92. var
  93.  i: integer;
  94.  obj: THashObj;
  95. begin
  96.    for i:=0 to HashElements.Count-1 do begin
  97.       obj := HashElements.items[i];
  98.       HashElements.delete(i);
  99.       obj.Free;
  100.    end;
  101.   HashElements.Free;
  102.   inherited destroy;
  103. end;
  104.  
  105.  
  106. function THashSlot.GetObjByName( Name: pChar ): THashObj;
  107. var
  108.  i: integer;
  109.  HO: THashObj;
  110.  
  111. begin
  112.  Result := NIL;
  113.  for i:=0 to HashElements.Count-1 do begin
  114.     HO := HashElements.items[i];
  115.     if (strcomp( pChar(HO.Name), Name) = 0) then begin
  116.          Result:= HO;
  117.          exit;
  118.     end;
  119.  end;
  120. end;
  121.  
  122.  
  123.  
  124. //--------------------------------------------------
  125. //
  126. //  THashTable
  127. //
  128. //--------------------------------------------------
  129. constructor THashTable.Create;
  130. begin
  131.   inherited Create;
  132.   HashElementList:= TList.Create;
  133. end;
  134.  
  135.  
  136. destructor THashTable.Destroy;
  137. var
  138.   i: integer;
  139. begin
  140.  for i:=0 to HashElementList.Count-1 do begin
  141.     HashSlot := HashElementList.Items[i];
  142.     HashSlot.Free;
  143.     HashElementList.Delete(i);
  144.  end;
  145.  HashElementList.Free;
  146.  inherited Destroy;
  147. end;
  148.  
  149.  
  150.  
  151. procedure THashTable.Init(Size: integer);
  152. var
  153.  i: integer;
  154. begin
  155.  
  156.  if Size <= 100 then
  157.     ClosestPrime := 97
  158.  
  159.  else if (Size >100) and (Size <= 250) then
  160.     ClosestPrime := 241
  161.  
  162.  else if (Size >250) and (Size <= 400) then
  163.     ClosestPrime := 397
  164.  
  165.  else if (Size >400) and (Size <= 500) then
  166.     ClosestPrime := 499
  167.  
  168.  else if (Size >500) and (Size <= 750) then
  169.     ClosestPrime := 743
  170.  
  171.  else if (Size >750) and (Size <= 1000) then
  172.     ClosestPrime := 997
  173.  
  174.  else if (Size >1000) and (Size <= 1500) then
  175.     ClosestPrime := 1499
  176.  
  177.  else if (Size >1500) and (Size <= 2000) then
  178.     ClosestPrime := 1999
  179.  
  180.  else if (Size >2000) and (Size <= 4000) then
  181.     ClosestPrime := 3989
  182.  
  183.  else if (Size >4000) and (Size <= 5000) then
  184.     ClosestPrime := 4999
  185.  
  186.  
  187.  else if (Size >5000) and (Size <= 7500) then
  188.     ClosestPrime := 7499
  189.  
  190.  else if (Size >7500) and (Size <= 10000) then
  191.     ClosestPrime := 9973;
  192.  
  193.  for i:=0 to Size do begin
  194.     HashSlot := THashSlot.Create;
  195.     HashSlot.SlotOfHashValue := i;
  196.     HashElementList.Add( HashSlot);
  197.  end;
  198.  
  199. end;
  200.  
  201. procedure THashTable.AddElementToSlot( Element: String; Data: Pointer);
  202. var
  203.   HS: THashSlot;
  204. begin
  205.   HashElement := THashObj.Create;
  206.   HashElement.HashValue := ElfHash( pchar(Trim(Element)) ) mod ClosestPrime;
  207.   HashElement.Name := Element;
  208.   HashElement.Data := Data;
  209.  
  210.   HS := HashElementList.items[HashElement.HashValue ];
  211.  
  212.   HS.HashElements.Add( HashElement);
  213. end;
  214.  
  215.  
  216. procedure THashTable.DelElementFromSlot( Element: String );
  217. var
  218.   HashValue: integer;
  219.   HS: ThashSlot;
  220. begin
  221.   HashValue := ElfHash(pchar(trim(Element))) mod ClosestPrime;
  222.  
  223.   HS := HashElementList.items[HashValue ];
  224.  
  225.   HashElement := HS.GetObjByName( pchar(Element) );
  226.   HashElement.Free;
  227.   HS.HashElements.Remove( HashElement );
  228.   HS.HashElements.Pack;
  229. end;
  230.  
  231.  
  232. function THashTable.CountElementsInSlot( SlotOfValues: String): integer;
  233. var
  234.   HashValue: integer;
  235.   HS: ThashSlot;
  236. begin
  237.   HashValue := ElfHash(pchar(trim(SlotOfValues))) mod ClosestPrime;
  238.  
  239.   HS := HashElementList.items[HashValue ];
  240.  
  241.   Result := HS.HashElements.count;
  242. end;
  243.  
  244.  
  245. function THashTable.GetElementFromSlot( Name: String): THashObj;
  246. var
  247.   HashValue: integer;
  248.   HS: ThashSlot;
  249. begin
  250.   HashValue := ElfHash(pchar(trim(Name))) mod ClosestPrime;
  251.  
  252.   HS := HashElementList.items[HashValue ];
  253.  
  254.   Result := HS.GetObjByName( pchar(Name) );
  255. end;
  256.  
  257.  
  258. function THashTable.GetSlot( Slot: string): TList;
  259. var
  260.   HS: THashSlot;
  261.   HashValue: integer;
  262. begin
  263.   HashValue := ElfHash(pchar(trim(Slot))) mod ClosestPrime;
  264.  
  265.   HS := HashElementList.items[ HashValue ];
  266.  
  267.   Result := HS.HashElements;
  268. end;
  269.  
  270.  
  271. function THashTable.ElfHash( name: pchar): integer;
  272. var
  273.  h,g: word;
  274.  i, nCount: integer;
  275.  
  276. begin
  277.  h:=0;
  278.  nCount := StrLen(name);
  279.  
  280.  for i:=0 to nCount-1 do begin
  281.     h :=  ( h shl 4 ) + integer(name[i+1]);
  282.     g := h AND $F0000000;
  283.     if ( g <> 0  ) then begin
  284.         h := h xor ( g shr 24 );
  285.         h := h AND (not(g));
  286.      end;   
  287.  end;
  288.  Result := h;
  289. end;
  290.  
  291.  
  292. end.
  293.